package org.labo.sigmalivepaper;

import java.util.List;

import org.labo.sigmalivepaper.BatimentEnum;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.StrictMode;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import aurelienribon.tweenengine.Timeline;
import aurelienribon.tweenengine.Tween;
import aurelienribon.tweenengine.TweenManager;
import aurelienribon.tweenengine.equations.Elastic;

public class SigmaWallpaperService extends WallpaperService {

	private SensorManager sensorManager;
	private Sensor accelerometer;
		
	@Override
	public Engine onCreateEngine() {		
		try {
			return new MyWallpaperEngine();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(e);
			throw new RuntimeException(e);
		}
	}
	

	private class MyWallpaperEngine extends Engine implements SensorEventListener {		
		
		private LocationManager locationManager;
		private LocationListener locationListener;
	    private String provider;
		
		private void initLocation() {
			locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
			List<String> providers = locationManager.getProviders(true);
			for (String provider : providers) {
				System.out.println(provider);
			}
			//sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
			
			locationListener = new LocationListener() {
				@Override
			    public void onLocationChanged(Location location) {
					System.out.println(location.getLatitude());
					System.out.println(location.getLongitude());
					
					System.out.println(BatimentEnum.GPS.BAT_1.contains(location.getLatitude(), location.getLongitude()));
					System.out.println(BatimentEnum.GPS.BAT_6.contains(location.getLatitude(), location.getLongitude()));
			    }

				@Override
				public void onProviderDisabled(String arg0) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void onProviderEnabled(String arg0) {
					// TODO Auto-generated method stub
					
				}

				@Override
				public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
					// TODO Auto-generated method stub
					
				}
			};
			
			locationManager.requestLocationUpdates("gps", 0, 0, locationListener);
		}
		
		public Sprite logo;
		TweenManager manager;
		
		private final Handler handler = new Handler();
		private SurfaceHolder holder;
		
		private Thread loopAnimation;
		public boolean isAnimationRunning = false;
		
		private boolean visible = true;
		
		private float accel; // acceleration apart from gravity
		private float accelCurrent; // current acceleration including gravity
		private float accelLast; // last acceleration including gravity

		boolean initialized = false;
		
		float lastX = 0.0f;
		float lastY = 0.0f;
		
		float x = 0.0f;
		float y = 0.0f;
		
		private final float NOISE = (float) 2.0;

		@Override
		public void onAccuracyChanged(Sensor sensor, int accuracy) {			
		}

		@Override
		public void onSensorChanged(SensorEvent event) {
			
			 x = event.values[0];
			 y = event.values[1];
			 float z = event.values[2];
			
			 if (!initialized) {
				 lastX = x;
				 lastY = y;
				 initialized = true;
			} else {
				float deltaX = lastX - x;
				float deltaY = lastY - y;

				if (Math.abs(deltaX*10) < NOISE)
					deltaX = (float) 0.0;
				if (Math.abs(deltaY*30) < NOISE)
					deltaY = (float) 0.0;
				
				lastX = x;
				lastY = y;
			 
			accelLast = accelCurrent;
			accelCurrent = (float) Math.sqrt((double) (x * x + y * y + z * z));
			float delta = accelCurrent - accelLast;
			accel = accel * 0.9f + delta; // perform low-cut filter
			
			
			Timeline.createSequence().push(Tween.to(logo, SpriteAccessor.POSITION_XY, 4.0f).target(deltaX*10, deltaY*30).ease(Elastic.OUT))
			.push(Tween.to(logo, SpriteAccessor.POSITION_XY, 1.0f).target(0, 0).ease(Elastic.OUT))
			.start(manager);
			}
		}
		
		private final Runnable drawRunner = new Runnable() {
			@Override
			public void run() {
				draw();
			}
		};
		
		private final Runnable sensorRunnable = new Runnable() {
			@Override
			public void run() {
				StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
		        StrictMode.setThreadPolicy(policy);
				
				//sensorManager = SensorManagerSimulator.getSystemService(getBaseContext(), SENSOR_SERVICE);
		        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
				accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
				//sensorManager.connectSimulator();
			}
		};
		
		@Override
		public void onSurfaceCreated(SurfaceHolder holder) {
			super.onSurfaceCreated(holder);
			visible = true;
			isAnimationRunning = true;
			loopAnimation.start();
		}
		
		@Override
		public void onSurfaceDestroyed(SurfaceHolder holder) {
			super.onSurfaceDestroyed(holder);
			visible = false;
			isAnimationRunning = false;
			handler.removeCallbacks(drawRunner);
			loopAnimation.interrupt();
			
			sensorManager.unregisterListener(this);
		}

		public MyWallpaperEngine() {
			accel = 0.00f;
		    accelCurrent = SensorManager.GRAVITY_EARTH;
		    accelLast = SensorManager.GRAVITY_EARTH;

			handler.post(sensorRunnable);
			
			initLocation();
			
			manager = new TweenManager();
			logo = new Sprite(getBaseContext());			
			Tween.registerAccessor(Sprite.class, new SpriteAccessor());
			
			loopAnimation = new Thread(new Runnable() {
			    private long lastMillis = -1;

			    @Override
			    public void run() {
			        while (isAnimationRunning) {
			            if (lastMillis > 0) {
			                long currentMillis = System.currentTimeMillis();
			                final float delta = (currentMillis - lastMillis) / 1000f;
		
			                handler.post(new Runnable() {
			                    @Override public void run() {
			                    	manager.update(delta);
			                    }
			                });
			                
			                lastMillis = currentMillis;
			            } else {
			                lastMillis = System.currentTimeMillis();
			            }

			            try {
			                Thread.sleep(1000/60);
			            } catch(InterruptedException ex) {
			            }
			        }
			    }
			});
		}
		
		@Override
		public void onVisibilityChanged(boolean visible) {
			this.visible = visible;
			if (visible) {
				handler.post(drawRunner);
				synchronized (loopAnimation) {
					loopAnimation.notify();
				}
				if (sensorManager != null && accelerometer != null ) {
					sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
				}
			} else {
				handler.removeCallbacks(drawRunner);
				synchronized (loopAnimation) {
					try {
						loopAnimation.wait(1000);
					} catch (InterruptedException e) {
					}
				}
				if (sensorManager != null ) {
					sensorManager.unregisterListener(this);
				}
			}
		}

		/*@Override
		public void onTouchEvent(MotionEvent event) {
			float x = event.getRawX();
			float y = event.getRawY();
			 
			Timeline.createSequence().push(Tween.to(logo, SpriteAccessor.POSITION_XY, 4.0f).target(x-(logo.getX()+logo.getOffsetX()), y-(logo.getY()+logo.getOffsetY())).ease(Elastic.OUT))
			.push(Tween.to(logo, SpriteAccessor.POSITION_XY, 1.0f).target(0, 0).ease(Elastic.OUT))
			.start(manager);
			

			super.onTouchEvent(event);
		}*/

		private void draw() {
			Canvas canvas = null;
			try {
				holder = getSurfaceHolder();
				canvas = holder.lockCanvas();	
				if ( canvas != null ) {
					synchronized (holder) { 
						canvas.drawColor(Color.WHITE);
						logo.draw(canvas);
					}
				}
			} finally {
				if (canvas != null) {
					holder.unlockCanvasAndPost(canvas);
				}
			}
			
			handler.removeCallbacks(drawRunner);
			if (visible) {
				//handler.postDelayed(drawRunner, 1000/60);
			}
		}
	}

}
